/* 
 * File:   ConstanteParser.h
 * Author: Gab'z
 *
 * Created on 5 mai 2012, 22:47
 */

#ifndef CALCPARSER_H
#define	CALCPARSER_H
#include <string>
#include "Constante.h"
#include "constante_format_exception.h"
#include "OperateurMap.h"
#include "CalcObjet.h"

class CalcParser {
    OperateurMap* opMap;

public:

    CalcParser() {
        opMap = OperateurMap::getInstance();
    }
    virtual ~CalcParser();


    CalcObjet* parse(const std::string& str) const throw (ConstanteFormatException);

    bool isEntier(const std::string& str) const {
        const char* c = str.c_str();
        for (unsigned int i = 0; i < str.length(); i++, c++) {
            if (!(*c >= '0' && *c <= '9')) return false;
        }
        return true;
    }

    bool isRationnel(const std::string& str, int* pos) const {
        *pos = str.find("/", 0);
        // au moins un caractère avant un / d'où le 1 dans la comparaison
        if (*pos < 1) return false;
        // la partie rationnelle fait au moins 1 caractère
        if (str.length() - *pos < 1) return false;
        if (!(isEntier(str.substr(0, *pos))
                && isEntier(str.substr(*pos + 1, str.length() - *pos)))
                ) return false;
        // les 2 valeurs sont bien des entiers
        return true;
    }

    bool isReel(const std::string& str, int* pos) const {
        *pos = str.find(".", 0);
        // au moins un caractère avant un / d'où le 1 dans la comparaison
        if (*pos < 1) return false;
        // la partie décimale fait au moins 1 caractère
        if (str.length() - *pos < 1) return false;
        if (!(isEntier(str.substr(0, *pos))
                && isEntier(str.substr(*pos + 1, str.length() - *pos)))
                ) return false;
        // les 2 valeurs sont bien des entiers
        return true;
    }

    bool isComplexe(const std::string& str, int* pos) const {
        *pos = str.find("$", 0);
        // au moins un caractère avant un $ d'où le 1 dans la comparaison
        if (*pos < 1) return false;
        // la partie imaginaire fait au moins 1 caractère
        if (str.length() - *pos - 1 < 1) return false;
        if (!(isNombreSimple(str.substr(0, *pos))
                && isNombreSimple(str.substr(*pos + 1, str.length() - *pos)))
                ) return false;
        // les 2 valeurs sont bien des NombreSimple
        return true;
    }

    bool isNombreSimple(const std::string& str) const {
        int position = 0; //unused
        int* pos = &position;
        if (isEntier(str)
                || isRationnel(str, pos)
                || isReel(str, pos)) {
            delete pos;
            return true;
        }
        delete pos;
        return false;
    }

    bool isOperateur(const std::string& str) const {

        return opMap->isOperateurName(str);
    }
};

#endif	/* CALCPARSER_H */

